'use strict';

const Service = require('egg').Service;

const uuid = async conn => {
  const result = await conn.query("select REPLACE(UUID(),'-','') as uuid");
  return result[0].uuid;
};

const createPermission = async (conn, resource_id, action) => {
  const permission_id = await uuid(conn);

  await conn.insert('sys_permission', {
    id: permission_id,
    action,
    created_at: new Date(),
  });

  await conn.insert('sys_permission_resource', {
    permission_id,
    resource_id,
  });
};

class ResourceService extends Service {
  constructor(ctx) {
    super(ctx);
    this.name = 'resource';
  }

  // * resource -1-rp-n- permission -n---n- role
  async create(params) {
    const { mysql } = this.app;
    const conn = await mysql.beginTransaction();
    const { name, url, description, active = true } = params;
    const createTime = new Date();

    try {
      const resource_id = await uuid(conn);
      await conn.query(
        'INSERT INTO sys_resource(id,  name,  url,  description,  active, created_at) VALUES (?, ?, ?, ?, ?, ?);',
        [ resource_id, name, url, description, active, createTime ]
      );

      // permission
      await createPermission(conn, resource_id, '0');
      await createPermission(conn, resource_id, '1');
      await createPermission(conn, resource_id, '2');
      await createPermission(conn, resource_id, '3');

      await conn.commit();

      return {
        id: resource_id,
      };
    } catch (error) {
      console.log(error);
      this.ctx.throw(500, error.message);
      await conn.rollback();
    }
  }

  async find(params) {
    const { mysql } = this.app;
    const {
      helper: { pagination },
    } = this.ctx;
    try {
      const { name, url, description, active, page, size } = params;
      const pagger = pagination(page, size);
      const filters = {
        name: {
          '=': name,
        },
        url: {
          '=': url,
        },
        description: {
          '=': description,
        },
        active: {
          '=': active,
        },
      };
      const segments = [];
      const values = [];
      // const user_id = this.ctx.user.id;
      Object.keys(filters).forEach(key => {
        const item = filters[key];
        const k = Object.keys(item)[0];
        if (item[k]) {
          segments.push(`(${key} ${k} ? )`);
          values.push(item[k]);
        }
      });
      const select = 'SELECT `sys_resource`.`id`, `sys_resource`.`name`, `sys_resource`.`url`, `sys_resource`.`description`, `sys_resource`.`active`, `sys_resource`.`created_at`, `sys_permission_resource`.`permission_id`, `sys_permission`.`action` FROM `sys_permission`, `sys_resource`, `sys_permission_resource` WHERE `sys_permission`.`id` = `sys_permission_resource`.`permission_id` AND `sys_resource`.`id` = `sys_permission_resource`.`resource_id`';
      // const select = 'SELECT * FROM `sys_resource` WHERE id IN (SELECT resource_id FROM `sys_permission_resource`)';
      // const select = 'SELECT * FROM `sys_resource` WHERE id IN (SELECT resource_id FROM `sys_permission_resource` WHERE permission_id in ( SELECT `sys_role_permission`.`permission_id` FROM `sys_role`, `sys_permission`, `sys_role_permission` WHERE `sys_role`.`id` = `sys_role_permission`.`role_id` AND `sys_permission`.`id` = `sys_role_permission`.`permission_id` AND `sys_role`.`id` IN ( SELECT `sys_role`.`id` FROM `sys_user`, `sys_role`, `sys_user_role` WHERE `sys_user`.`id` = `sys_user_role`.`user_id` AND `sys_role`.`id` = `sys_user_role`.`role_id` AND `sys_user`.`id` = ? ) )) ';
      const wheres = segments.length ? `AND ${segments.join(' AND ')}` : '';
      const order = 'ORDER BY `created_at` ASC';
      const limit = 'LIMIT ? OFFSET ?';
      const count = await mysql.query(
        'SELECT COUNT(*) as `total` FROM (' + select + ') C ' + wheres,
        [ ...values ]
      );
      const result = await mysql.query(
        [ select, wheres, order, limit ].join(' '),
        [ ...values, pagger.limit, pagger.offset ]
      );
      return {
        pagination: {
          total: count[0].total,
          page: pagger.page,
          size: pagger.size,
        },
        list: result,
      };
    } catch (error) {
      this.ctx.throw(500);
    }
  }

  async findOne(params) {
    const { mysql } = this.app;
    try {
      const { id } = params;
      const result = await mysql.get('sys_resource', { id });
      return result;
    } catch (error) {
      this.ctx.throw(500, error.message);
    }
  }

  async update(params) {
    const { mysql } = this.app;
    try {
      const { id, name, url, description, active = true } = params;
      const updateTime = new Date();
      const result = await mysql.query(
        'UPDATE `sys_resource` SET `name`=?, `url`=?, `description`=?, `active`=?, `updated_at`=? WHERE `id`=?',
        [ name, url, description, active, updateTime, id ]
      );
      if (result.affectedRows === 1) {
        return {};
      }
    } catch (error) {
      this.ctx.throw(500, error.message);
    }
  }

  async destroy(params) {
    const { mysql } = this.app;
    try {
      const { id } = params;
      const result = await mysql.delete('cms_category', { category_id: id });
      if (result.affectedRows === 1) {
        return {};
      }
    } catch (error) {
      this.ctx.throw(500, error.message);
    }
  }
}

module.exports = ResourceService;
